package ar.edu.itba.pod.legajo47279;

import java.net.UnknownHostException;
import java.rmi.AlreadyBoundException;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;

import org.apache.log4j.Logger;

import ar.edu.itba.node.NodeInformation;
import ar.edu.itba.node.api.ClusterAdministration;

public class Main {

	private final int EXIT_VALUE = 99;
	private final int IDLE_VALUE = -1;

	private static final Logger LOGGER = Logger.getLogger(Main.class);

	private ClusterAdministration clusterAdministration = null;

	public static void main(String[] args) {
		new Main();
	}

	public Main() {
		int optionValue = IDLE_VALUE;

		//
		// Initialize stuff
		//
		String localIP;
		try {
			localIP = Utils.getLocalIP();
		} catch (UnknownHostException e) {
			LOGGER.error("Error when getting local IP address.", e);
			return;
		} 
		int port = Constants.REGISTRY_PORT;
		NodeInformation nodeInformation = new NodeInformation(localIP, port, localIP + port);
		
		try {
			clusterAdministration = new ClusterAdministrationRemoteObject(nodeInformation);
			Registry registry = LocateRegistry
					.createRegistry(Constants.REGISTRY_PORT);
			registry.bind(Constants.CLUSTER_ADMINISTRATION_NAME,
					clusterAdministration);

			LOGGER.info("ClusterAdministration binded at port "
					+ Constants.REGISTRY_PORT + ".");
		} catch (RemoteException e) {
			LOGGER.error("RemoteException when binding object of type: "
					+ ClusterAdministration.class.toString(), e);
		} catch (AlreadyBoundException e) {
			LOGGER.error("RemoteException when binding object of type: "
					+ ClusterAdministration.class.toString(), e);
		}

		//
		// Infinite loop
		//
		while (optionValue != EXIT_VALUE) {
			optionValue = IDLE_VALUE;
			// Display menu graphics
			System.out.println("=============================================");
			System.out.println("    POD 2011 - AGENT-BASED SIMULATION        ");
			System.out.println("=============================================");
			System.out.println("  Options:                                   ");
			System.out.println("         1. Create a new Group               ");
			System.out.println("         2. Connect to an existing Group     ");
			System.out.println("         " + EXIT_VALUE + ". Exit            ");
			System.out.println("=============================================");
			optionValue = Keyin.inInt(" Select option: ");

			switch (optionValue) {
			case 1:
				createNewCluster();
				break;
			case 2:
				connectToACluster();
				break;
			case EXIT_VALUE:
				System.out.println("Exit selected");
				break;
			default:
				System.out.println("Invalid selection");
				break;
			}
		}
	}

	
	/**
	 * 
	 * @method connectToACluster
	 */
	private void connectToACluster() {
		if (clusterAdministration == null) {
			throw new IllegalStateException(
					ClusterAdministration.class.toString()
							+ " object cannot be null.");
		}
		String remoteIPAddress = "";
		boolean isIPAddressValid = false;
		while(!isIPAddressValid)
		{
			remoteIPAddress = Keyin.inString(" Insert remote cluster IP address: ");
			isIPAddressValid = Utils.validate(remoteIPAddress); 
			if(!isIPAddressValid)	{
				System.out.println(" Invalid IP Address: " + remoteIPAddress);
			}
		}
		try {
			clusterAdministration.connectToGroup(remoteIPAddress, Constants.REGISTRY_PORT);
		} catch (RemoteException e) {
			LOGGER.error("Error when connecting to a group at: '" + remoteIPAddress + "'.", e);
		} catch (NotBoundException e) {
			LOGGER.error("Could not get stub objects from group at: '" + remoteIPAddress + "'.", e);
		}
	}

	
	/**
	 * 
	 * @method createNewCluster
	 */
	private void createNewCluster() {
		if (clusterAdministration == null) {
			throw new IllegalStateException(
					ClusterAdministration.class.toString()
							+ " object cannot be null.");
		}
		try {
			clusterAdministration.createGroup();
		} catch (IllegalStateException e) {
			LOGGER.error("Cluster already binded to a group.", e);
		} catch (RemoteException e) {
			LOGGER.error("Error when creating a group.", e);
		}
	}
}
